package com.lier.gulimall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lier.common.constant.ProductConstant;
import com.lier.gulimall.product.dao.AttrAttrgroupRelationDao;
import com.lier.gulimall.product.dao.AttrGroupDao;
import com.lier.gulimall.product.dao.CategoryDao;
import com.lier.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.lier.gulimall.product.entity.AttrGroupEntity;
import com.lier.gulimall.product.entity.CategoryEntity;
import com.lier.gulimall.product.service.AttrAttrgroupRelationService;
import com.lier.gulimall.product.service.CategoryService;
import com.lier.gulimall.product.vo.AttrResponseVo;
import com.lier.gulimall.product.vo.AttrVo;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lier.common.utils.PageUtils;
import com.lier.common.utils.Query;
import com.lier.gulimall.product.dao.AttrDao;
import com.lier.gulimall.product.entity.AttrEntity;
import com.lier.gulimall.product.service.AttrService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {

    @Resource
    private AttrAttrgroupRelationDao attrAttrgroupRelationDao;
    @Resource
    private AttrGroupDao attrGroupDao;
    @Resource
    private CategoryDao categoryDao;
    @Resource
    private CategoryService categoryService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<>()
        );

        return new PageUtils(page);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveAttr(AttrVo attrVo) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo, attrEntity);
        baseMapper.insert(attrEntity);

        if(attrVo.getAttrType().equals(ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode()) && attrVo.getAttrGroupId() != null){
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrId(attrEntity.getAttrId());
            attrAttrgroupRelationEntity.setAttrGroupId(attrVo.getAttrGroupId());
            attrAttrgroupRelationDao.insert(attrAttrgroupRelationEntity);
        }


    }

    @Override
    public PageUtils listAttr(Map<String, Object> params, Long catelogId, String attrType) {

        LambdaQueryWrapper<AttrEntity> attrEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 基础属性
        if(ProductConstant.AttrEnum.ATTR_TYPE_BASE.getType().equals(attrType)){
            attrEntityLambdaQueryWrapper.eq(AttrEntity::getAttrType, ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());
        }else {
            attrEntityLambdaQueryWrapper.eq(AttrEntity::getAttrType, ProductConstant.AttrEnum.ATTR_TYPE_SALE.getCode());
        }
        if(catelogId != 0){
            attrEntityLambdaQueryWrapper
                    .and(condition -> condition.eq(AttrEntity::getCatelogId, catelogId));
        }

        String key = (String)params.get("key");
        if(!StringUtils.isEmpty(key)){
            attrEntityLambdaQueryWrapper.and(conditional -> {
                conditional.eq(AttrEntity::getAttrId, key).or().like(AttrEntity::getAttrName, key);
            });
        }
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params), attrEntityLambdaQueryWrapper);
        PageUtils pageUtils = new PageUtils(page);
        List<AttrResponseVo> respVos = page.getRecords().stream().map(attrEntity -> {
            AttrResponseVo attrResponseVo = new AttrResponseVo();
            BeanUtils.copyProperties(attrEntity, attrResponseVo);

            CategoryEntity category = categoryDao.selectById(attrEntity.getCatelogId());
            if (category != null) {
                attrResponseVo.setCatelogName(category.getName());
            }
            if(ProductConstant.AttrEnum.ATTR_TYPE_BASE.getType().equals(attrType)){
                AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = attrAttrgroupRelationDao
                        .selectOne(new LambdaQueryWrapper<AttrAttrgroupRelationEntity>()
                                .eq(AttrAttrgroupRelationEntity::getAttrId, attrEntity.getAttrId()));
                if (attrAttrgroupRelationEntity != null) {
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrAttrgroupRelationEntity.getAttrGroupId());
                    if (attrGroupEntity != null) {
                        attrResponseVo.setGroupName(attrGroupEntity.getAttrGroupName());
                    }
                }
            }

            return attrResponseVo;
        }).collect(Collectors.toList());
        pageUtils.setList(respVos);
        return pageUtils;
    }

    @Cacheable(value = "attr", key = "'attrInfo:' + #root.args[0]")
    @Override
    public AttrResponseVo getAttrDetail(Long attrId) {
        AttrResponseVo attrResponseVo = new AttrResponseVo();
        AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity, attrResponseVo);

        // 设置其所属分组id
        if(ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode() == attrEntity.getAttrType()){
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = attrAttrgroupRelationDao
                    .selectOne(new LambdaQueryWrapper<AttrAttrgroupRelationEntity>()
                            .eq(AttrAttrgroupRelationEntity::getAttrId, attrEntity.getAttrId()));
            if (attrAttrgroupRelationEntity != null) {
                attrResponseVo.setAttrGroupId(attrAttrgroupRelationEntity.getAttrGroupId());
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrAttrgroupRelationEntity.getAttrGroupId());
                if(attrGroupEntity != null){
                    attrResponseVo.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
        }
        // 设置其分类路径
        List<Long> catelogPath = categoryService.findCatelogPath(attrEntity.getCatelogId());
        attrResponseVo.setCatelogPath(catelogPath);
        CategoryEntity category = categoryDao.selectById(attrEntity.getCatelogId());
        if (category != null) {
            attrResponseVo.setCatelogName(category.getName());
        }

        return attrResponseVo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateAttr(AttrVo attrVo) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVo, attrEntity);
        this.updateById(attrEntity);


        if(attrVo.getAttrType().equals(ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode())){

            int count = attrAttrgroupRelationDao.selectCount(new LambdaQueryWrapper<AttrAttrgroupRelationEntity>()
                    .eq(AttrAttrgroupRelationEntity::getAttrId, attrVo.getAttrId()));
            if(count > 0){
                LambdaUpdateWrapper<AttrAttrgroupRelationEntity> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(AttrAttrgroupRelationEntity::getAttrGroupId, attrVo.getAttrGroupId())
                        .eq(AttrAttrgroupRelationEntity::getAttrId, attrVo.getAttrId());

                attrAttrgroupRelationDao.update(null, updateWrapper);
            }else{
                AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
                attrAttrgroupRelationEntity.setAttrId(attrVo.getAttrId());
                attrAttrgroupRelationEntity.setAttrGroupId(attrVo.getAttrGroupId());
                attrAttrgroupRelationDao.insert(attrAttrgroupRelationEntity);
            }
        }
    }

    @Override
    public PageUtils getRelationNoAttr(Map<String, Object> params, Long attrgroupId) {
        AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);

        if(attrGroupEntity == null){
            return null;
        }

        // 当前分组只能关联别的分组没有引用的属性
        // 1: 获取当前分类下的其他分组
        LambdaQueryWrapper<AttrGroupEntity> attrGroupEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        attrGroupEntityLambdaQueryWrapper.eq(AttrGroupEntity::getCatelogId, attrGroupEntity.getCatelogId());
        List<AttrGroupEntity> otherGroupList = attrGroupDao.selectList(attrGroupEntityLambdaQueryWrapper);
        List<Long> otherGroupIds = otherGroupList.stream().map(AttrGroupEntity::getAttrGroupId).collect(Collectors.toList());
        // 2: 获取这些分组的所有属性
        LambdaUpdateWrapper<AttrAttrgroupRelationEntity> attrAttrgroupRelationEntityLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        if(!otherGroupIds.isEmpty()){
            attrAttrgroupRelationEntityLambdaUpdateWrapper.in(AttrAttrgroupRelationEntity::getAttrGroupId, otherGroupIds);
        }
        List<AttrAttrgroupRelationEntity> attrAttrgroupRelationEntities = attrAttrgroupRelationDao.selectList(attrAttrgroupRelationEntityLambdaUpdateWrapper);
        List<Long> attrIds = attrAttrgroupRelationEntities.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());
        // 3: 从当前分类的所有属性中中去掉这些属性
        LambdaUpdateWrapper<AttrEntity> attrEntityLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        attrEntityLambdaUpdateWrapper.eq(AttrEntity::getCatelogId, attrGroupEntity.getCatelogId())
                .eq(AttrEntity::getAttrType, ProductConstant.AttrEnum.ATTR_TYPE_BASE.getCode());

        if(!attrIds.isEmpty()){
            attrEntityLambdaUpdateWrapper.and(w -> {
                w.notIn(AttrEntity::getAttrId, attrIds);
            });
        }

        String key = (String)params.get("key");
        if(key != null && !StringUtils.isEmpty(key)){
            attrEntityLambdaUpdateWrapper.and(conditional -> {
                conditional.eq(AttrEntity::getAttrId, key).or().like(AttrEntity::getAttrName, key);
            });
        }
        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), attrEntityLambdaUpdateWrapper);
        return new PageUtils(page);
    }

    @Override
    public List<Long> selectSearchAttrs(List<Long> attrIdList) {

        return baseMapper.selectSearchAttrs(attrIdList);
    }

    @Override
    public List<AttrEntity> selectListByAttrIdList(List<Long> attrIdList) {
        return baseMapper.selectList(new LambdaQueryWrapper<AttrEntity>().in(AttrEntity::getAttrId, attrIdList));
    }
}
